//------------------------------------------------------------------------------
// Copyright (c) 2008 www.dnaide.com
// Licensed under the MIT (MIT-LICENSE.txt)
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Configuration;

namespace DNAide.Configuration
{

	/// <summary>
	/// A UrlRewriter rule
	/// </summary>
	public class UrlRewriterRuleConfig : ConfigurationElement
	{
		
		internal object _lock = new object();
		private Regex _matchExpressionRegex;

		/// <summary></summary>
		public UrlRewriterRuleConfig()
		{
		}

		/// <summary>
		/// The Match Expression as a Regex object
		/// </summary>
		public Regex MatchExpressionRegex
		{
			get
			{
				if (_matchExpressionRegex == null)
				{
					lock (_lock)
					{
						if (_matchExpressionRegex == null)
						{
							if (DNAideConfigurationSettings.Web.UrlRewriter.RegexCompilationMode == RegexCompilationType.Compiled)
							{
								_matchExpressionRegex = new Regex(DNAide.Web.UrlAide.Resolve(MatchExpression), RegexOptions.IgnoreCase | RegexOptions.Compiled);
							}
							else
							{
								_matchExpressionRegex = new Regex(DNAide.Web.UrlAide.Resolve(MatchExpression), RegexOptions.IgnoreCase);
							}
						}
					}
				}
				return _matchExpressionRegex;
			}
		}

		/// <summary>
		/// Rule identity.
		/// </summary>
		[ConfigurationProperty("id", IsRequired = true)]
		[StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'\"|\\")]
		public String Id
		{
			get
			{
				return (string)this["id"];
			}
			set
			{
				this["id"] = value;
			}
		}

		/// <summary>
		/// Regular expression to match against the requested url.
		/// </summary>
		[ConfigurationProperty("matchExpression", IsRequired = true)]
		public String MatchExpression
		{
			get
			{
				return (string)this["matchExpression"];
			}
			set
			{
				this["matchExpression"] = value;
			}
		}

		/// <summary>
		/// Destination. This can be either a URL or SiteMap node key
		/// </summary>
		[ConfigurationProperty("destination", IsRequired = false)]
		public String Destination
		{
			get
			{
				return (string)this["destination"];
			}
			set
			{
				this["destination"] = value;
			}
		}

		/// <summary>
		/// Destination type, UrlPattern, SiteMapNodeKey or Ignore. Default "UrlPattern".
		/// Ignore tells the rewriter to do nothing if a pattern is matched.
		/// </summary>
		[ConfigurationProperty("destinationType", DefaultValue = "UrlPattern")]
		public UrlRewriterRuleDestinationType DestinationType
		{
			get
			{
				return (UrlRewriterRuleDestinationType)this["destinationType"];
			}
			set
			{
				this["destinationType"] = value;
			}
		}

		/// <summary>
		/// Rule type, either "Rewrite" or "Redirect". Default "Rewrite"
		/// </summary>
		[ConfigurationProperty("ruleType", IsRequired = false, DefaultValue="Rewrite")]
		public UrlRewriterRuleType RuleType
		{
			get
			{
				return (UrlRewriterRuleType)this["ruleType"];
			}
			set
			{
				this["ruleType"] = value;
			}
		}


		/// <summary>
		/// Redirect status code. If the rule performs a redirect, this code is added as part of the response. Default value = 301 (Moved permanently)
		/// </summary>
		[ConfigurationProperty("redirectStatusCode", DefaultValue=301)]
		public Int32 RedirectStatusCode
		{
			get
			{
				return (int)this["redirectStatusCode"];
			}
			set
			{
				this["redirectStatusCode"] = value;
			}
		}


	}


	/// <summary>UrlRewriterRuleConfigCollection</summary>
	public class UrlRewriterRuleConfigCollection : ConfigurationElementCollection, ICollection<UrlRewriterRuleConfig>
	{
		/// <summary>IsReadOnly</summary>
		public new bool IsReadOnly
		{
			get
			{
				return base.IsReadOnly();
			}
		}

		/// <summary>UrlRewriterRuleConfig</summary>
		public UrlRewriterRuleConfig this[int index]
		{
			get
			{
				return (UrlRewriterRuleConfig)BaseGet(index);
			}
			set
			{
				if (BaseGet(index) != null)
				{
					BaseRemoveAt(index);
				}
				BaseAdd(index, value);
			}
		}

		/// <summary>UrlRewriterRuleConfig</summary>
		new public UrlRewriterRuleConfig this[string id]
		{
			get
			{
				return (UrlRewriterRuleConfig)BaseGet(id);
			}
		}

		/// <summary>UrlRewriterRuleConfigCollection</summary>
		public UrlRewriterRuleConfigCollection()
		{
		}

		/// <summary>Add</summary>
		public void Add(UrlRewriterRuleConfig item)
		{
			if (item == null)
				return;

			BaseAdd(item);
		}

		/// <summary>Clear</summary>
		public void Clear()
		{
			BaseClear();
		}

		/// <summary>Contains</summary>
		public bool Contains(UrlRewriterRuleConfig item)
		{
			if (BaseIndexOf(item) >= 0)
				return true;
			else
				return false;
		}

		/// <summary>CopyTo</summary>
		public void CopyTo(UrlRewriterRuleConfig[] array, int arrayIndex)
		{
			((ICollection)this).CopyTo(array, arrayIndex);
		}

		/// <summary>CreateNewElement</summary>
		protected override ConfigurationElement CreateNewElement()
		{
			return new UrlRewriterRuleConfig();
		}

		/// <summary>IndexOf</summary>
		public int IndexOf(UrlRewriterRuleConfig item)
		{
			if (item == null)
				return -1;

			return BaseIndexOf(item);
		}

		/// <summary>GetElementKey</summary>
		protected override object GetElementKey(ConfigurationElement element)
		{
			return ((UrlRewriterRuleConfig)element).Id;
		}

		/// <summary>GetEnumerator</summary>
		public new IEnumerator<UrlRewriterRuleConfig> GetEnumerator()
		{
			for (int i = 0; i < Count; i++)
			{
				yield return (UrlRewriterRuleConfig)this[i];
			}
		}

		/// <summary>Remove</summary>
		public bool Remove(UrlRewriterRuleConfig item)
		{
			if (item == null)
				return false;

			if (BaseIndexOf(item) >= 0)
				BaseRemove(item.Id);

			return true;
		}

		/// <summary>Remove</summary>
		public void Remove(string id)
		{	
			BaseRemove(id);
		}

		/// <summary>RemoveAt</summary>
		public void RemoveAt(int index)
		{
			BaseRemoveAt(index);
		}

	}

}
